package com.winning.pmph.ctrl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import com.winning.pmph.entity.Journal;
import com.winning.pmph.entity.JournalArticle;
import com.winning.pmph.service.JournalService;
import com.winning.pmph.utils.*;
import com.winning.pmph.vo.CascaderOption;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 刘亚飞
 * @Description
 * @create 2021-07-15 9:34
 */
@Api(value = "知识资源管理/期刊管理")
@Slf4j
@RestController
@RequestMapping("/pmph/action/journal")
public class JournalCtrl {

    @Resource
    private JournalService journalService;

    @ApiOperation(value = "uploadAndParse", notes = "导入期刊接口")
    @PostMapping("uploadAndParse")
    public String uploadAndParse(MultipartFile file, String journalId, HttpServletRequest request) {
        String header = request.getHeader("user-agent");
        String userEnName = PMPHAppUtil.getCurrentUserEnName();
        String path = ApplicationContextUtil.BASE_DOWN_FORDER + "image/journal/";

        String name = UploadFileUtil.uploadFile(file, path, false);
        // 文件上传成功后,开始解析,另起线程解析zip包
        // 向journal表插入数据
        Journal journal = new Journal();
        if (StringUtils.isNotBlank(journalId)) {
            journal.setId(journalId);
        }
        journal.setName(StringUtils.removeEnd(name, ".zip"));
        journal.setFilePath(path + name);
        journal.setUnZipPath(path + name);
        journal.setCreatedBy(userEnName);
        journal.setCreatedTime(LocalDateTimeUtil.getNowAsString());
        journal.setUpdatedBy(userEnName);
        journal.setUpdatedTime(LocalDateTimeUtil.getNowAsString());
        journal.setStatus(Journal.STATUS_IMPORTING);
        journal.setType(Journal.TYPE_DRAFT);
        journalService.saveOrUpdate(journal);
        // 另起线程解析zip包
        ExecutorServiceFactory.getInstance().submit(() -> {
            try {
                //开始解压图书
                journalService.uploadAndParse(journal, header);
            } catch (Exception e) {
                journal.setStatus(Journal.STATUS_IMPORT_FAILURE);
                journal.setFailureReason(e.toString());
                e.printStackTrace();
                log.error("图书: " + journal.getName() + ",上传失败: ", e);
            } finally {
                journalService.saveOrUpdate(journal);
                // 删除解压后的文件
                try {
                    FileUtils.deleteDirectory(new File(StringUtils.removeEnd(journal.getUnZipPath(), ".zip")));
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new RuntimeException(e.getMessage());
                }
                // 导入成功后删除上传的zip包文件;
                if (Journal.STATUS_IMPORT_SUCCESS == journal.getStatus()) {
                    FileUtils.deleteQuietly(new File(journal.getUnZipPath()));
                }
            }
        });
        return "导入任务提交成功, 请耐心等待";
    }

    @ApiOperation(value = "selectList", notes = "查询期刊列表")
    @GetMapping("selectList")
    public Map<String, Object> selectList(Integer currentPage,
                                          Integer pageSize,
                                          String searchJournal) {
        boolean isfinish = true;
        Map<String, Object> map = Maps.newHashMap();
        Journal journal = JSON.parseObject(searchJournal, Journal.class);
        Page page = new Page(currentPage, pageSize);
        if (StringUtils.isNotBlank(journal.getImportDate())) {
            journal.setImportStartDate(JSON.parseArray(journal.getImportDate()).getString(0));
            journal.setImportEndDate(JSON.parseArray(journal.getImportDate()).getString(1));
        }
        if (StringUtils.isNotBlank(journal.getReleaseTime())) {
            journal.setReleaseStartDate(JSON.parseArray(journal.getReleaseTime()).getString(0));
            journal.setReleaseEndDate(JSON.parseArray(journal.getReleaseTime()).getString(1));
        }
        page = journalService.queryList(page, journal);
        if (journalService.getImportingJournal().size() > 0) {
            isfinish = false;
        }
        map.put("isfinish", isfinish);
        map.put("journalIPage", page);
        return map;
    }

    @ApiOperation(value = "updateMetadataById", notes = "修改期刊元数据")
    @PostMapping("updateMetadataById")
    public void updateMetadataById(String data, String id) {
        // issn,volume,issue 不能修改原因,issn关联平台,且三者组合作为图片路径,所以不能修改
        JSONObject metadataJson = JSONObject.parseObject(data);
        Journal journal = journalService.getById(id);
        String name = metadataJson.getJSONObject("journal-title-group").getJSONArray("journal-title").getString(0);
        journal.setMetadata(data);
        journal.setName(name);
        journalService.updateById(journal);
    }

    @ApiOperation(value = "selectArticleList", notes = "查询期刊目录列表")
    @PostMapping("selectArticleList")
    public Page<JournalArticle> selectArticleList(String journalArticleStr,
                                                  Integer currentPage,
                                                  Integer pageSize) {
        JournalArticle journalArticle = JSONObject.toJavaObject(JSON.parseObject(journalArticleStr), JournalArticle.class);
        return journalService.queryArticleByJournalId(new Page(currentPage, pageSize), journalArticle);
    }

    @ApiOperation(value = "selectArticleCatalogTree", notes = "查询期刊目录树结构")
    @GetMapping("selectArticleCatalogTree")
    public Map<String, String> selectArticleCatalogTree(String id) {
        Map<String, String> map = Maps.newHashMap();
        JournalArticle journalArticle = journalService.getArticleById(id);
        map.put("catalog", journalArticle.getCatalog());
        map.put("textarea", journalArticle.getBody());
        map.put("name", journalArticle.getName());
        return map;
    }

    @ApiOperation(value = "editConfirm", notes = "期刊目录编辑页面保存按钮接口")
    @PostMapping("editConfirm")
    public void editConfirm(String articleId,
                            String unitContent) {
        JournalArticle journalArticle = new JournalArticle();
        journalArticle.setId(articleId);
        journalArticle.setBody(unitContent);
        journalService.updateArticleById(journalArticle);
    }

    @ApiOperation(value = "release", notes = "期刊列表发布接口")
    @PostMapping("release")
    public void release(String id) {
        Journal journal = journalService.getById(id);
        journalService.updateJournalByJournal(journal);
    }

    @ApiOperation(value = "releaseSelected", notes = "期刊列表批量发布接口")
    @PostMapping("releaseSelected")
    public void releaseSelected(String selection) {
        List<Journal> journals = JSON.parseArray(selection, Journal.class);
        for (Journal journal : journals) {
            journalService.updateJournalByJournal(journal);
        }
    }

    @ApiOperation(value = "releaseAll", notes = "期刊列表一键发布接口")
    @PostMapping("releaseAll")
    public void releaseAll(String searchJournal) {
        Journal journal = JSON.parseObject(searchJournal, Journal.class);
        LambdaQueryWrapper<Journal> wrapper = Wrappers.lambdaQuery(Journal.class).eq(StringUtils.isNotBlank(journal.getName()), Journal::getName, journal.getName())
                .eq(StringUtils.isNotBlank(journal.getCategory()), Journal::getCategory, journal.getCategory())
                .eq(StringUtils.isNotBlank(journal.getCn()), Journal::getCn, journal.getCn())
                .eq(StringUtils.isNotBlank(journal.getIssn()), Journal::getIssn, journal.getIssn())
                .eq(Journal::getStatus, Journal.STATUS_IMPORT_SUCCESS);
        if (StringUtils.isNotBlank(journal.getImportDate())) {
            wrapper.ge(Journal::getUpdatedTime, journal.getImportDate().split(",")[0].trim())
                    .ge(Journal::getUpdatedTime, journal.getImportDate().split(",")[1].trim());
        }
        List<Journal> records = journalService.page(new Page<>(), wrapper).getRecords();
        for (Journal record : records) {
            journalService.updateJournalByJournal(record);
        }
    }

    @ApiOperation(value = "selectJournalLibs", notes = "期刊推送选择推送平台接口")
    @GetMapping("selectJournalLibs")
    public List<Journal> selectJournalLibs() {
        List<Journal> journalList = journalService.getJournalLibs();
        return journalList;
    }

    @ApiOperation(value = "selectJournalCascaderOptions", notes = "期刊级联选择框数据")
    @GetMapping("selectJournalCascaderOptions")
    public List<CascaderOption> selectJournalCascaderOptions() {
        List<CascaderOption> result = new ArrayList<>();
        List<Journal> journalList = journalService.lambdaQuery()
                .eq(Journal::getStatus, Journal.STATUS_IMPORT_SUCCESS)
                .orderByAsc(Journal::getName, Journal::getVolume, Journal::getIssue).list();
        for (Journal journal : journalList) {
            // 一级, id为issn, name 为期刊名;
            CascaderOption topOption = null;
            Optional<CascaderOption> issnOption = result.stream().filter(item -> StringUtils.equals(item.getId(), journal.getIssn())).findFirst();
            if (issnOption.isPresent()) {
                topOption = issnOption.get();
            } else {
                topOption = new CascaderOption(journal.getIssn(), journal.getName());
                topOption.setChildren(new ArrayList<>());
                result.add(topOption);
            }
            // 二级为id,name 都是  年 + volume;
            String secondLevelOptionKey = journal.getVolume() + "卷";
            // 获取年份;
            String year = null;
            JSONObject metadata = JSON.parseObject(journal.getMetadata());
            if (Objects.nonNull(metadata)) {
                JSONObject pubDate = metadata.getJSONObject("pub-date");
                if (Objects.nonNull(pubDate)) {
                    year = pubDate.getString("year");
                }
            }
            if (StringUtils.isNotEmpty(year)) {
                secondLevelOptionKey = year + "年(" + secondLevelOptionKey + ")";
            }
            CascaderOption secondLevelOption = null;
            String finalSecondLevelOptionKey = secondLevelOptionKey;
            Optional<CascaderOption> volumeOption = topOption.getChildren().stream()
                    .filter(item -> StringUtils.equals(item.getId(), finalSecondLevelOptionKey))
                    .findFirst();
            if (volumeOption.isPresent()) {
                secondLevelOption = volumeOption.get();
            } else {
                secondLevelOption = new CascaderOption(secondLevelOptionKey, secondLevelOptionKey);
                secondLevelOption.setChildren(new ArrayList<>());
                topOption.getChildren().add(secondLevelOption);
            }
            // 三级name为issue, id为具体期刊id;
            CascaderOption thirdLevelOption = new CascaderOption(journal.getId(), journal.getIssue() + "期");
            secondLevelOption.getChildren().add(thirdLevelOption);
        }
        return result;
    }

    @ApiOperation(value = "syncToPlatform", notes = "期刊推送接口")
    @PostMapping("syncToPlatform")
    public String syncToPlatform(String searchParams) {
        Journal journal = JSONObject.parseObject(searchParams, Journal.class);
        if (StringUtils.isBlank(journal.getId())) {
            journal.setId(journalService.queryList(new Page<Journal>(), journal).getRecords().stream().map(Journal::getId).collect(Collectors.joining(",")));
        }
        String userName = PMPHAppUtil.getCurrentUserEnName();
        ExecutorServiceFactory.getInstance().submit(() -> {
            journalService.syncToPlatform(journal, userName, Const.SYNC_OPERATION_ADD);
        });
        return "推送任务提交成功, 请稍后查看推送状态";
    }

    @ApiOperation(value = "selectShowAuthor", notes = "期刊展示作者信息接口")
    @PostMapping("selectShowAuthor")
    public JSONArray selectShowAuthor(String data) {
        JSONArray resultArray = new JSONArray();
        JSONObject jsonObject = JSON.parseObject(data);
        // 拼接文章作者
        JSONArray contribGroupArray = jsonObject.getJSONArray("contrib-group");
        contribGroupArray.forEach(t -> {
            ((JSONObject) t).getJSONArray("contrib").forEach(t1 -> {
                JSONObject authorObject = new JSONObject();
                if ("author".equals(((JSONObject) t1).getString("contrib-type"))) {
                    // 作者有(也可能没有)地址和email,编者无,关联下地址和email
                    Object xrefObject = ((JSONObject) t1).get("xref");
                    JSONArray xrefArray = new JSONArray();
                    if (Objects.nonNull(xrefObject)) {
                        if (xrefObject instanceof JSONObject) {
                            xrefArray.add(xrefObject);
                            ((JSONObject) t1).put("xref", xrefArray);
                        } else {
                            xrefArray = ((JSONObject) t1).getJSONArray("xref");
                        }
                        xrefArray.forEach(xref -> {
                            String refType = ((JSONObject) xref).getString("ref-type");
                            String rid = ((JSONObject) xref).getString("rid");
                            if ("aff".equals(refType)) {
                                // 地址
                                JSONArray affArray = jsonObject.getJSONArray("aff-alternatives");
                                affArray.forEach(t2 -> {
                                    if (rid.equals(((JSONObject) t2).getString("id"))) {
                                        JSONArray affChildArray = ((JSONObject) t2).getJSONArray("aff");
                                        // 为前台展示美观,去掉Label标签
                                        authorObject.put("address", JsoupUtil.removeLabel(affChildArray.getString(0), "label"));
                                        if (affChildArray.size() > 1) {
                                            authorObject.put("engAddress", JsoupUtil.removeLabel(affChildArray.getJSONObject(1).getString("content"), "label"));
                                        }
                                    }
                                });
                            } else if ("corresp".equals(refType) || "author-notes".equals(refType)) {
                                // email
                                JSONArray affArray = jsonObject.getJSONArray("author-notes");
                                affArray.forEach(t2 -> {
                                    JSONArray correspArray = ((JSONObject) t2).getJSONArray("corresp");
                                    if (rid.equals(correspArray.getJSONObject(0).getString("id"))) {
                                        authorObject.put("email", correspArray.getJSONObject(0).getString("email"));
                                    }
                                });
                            } else {
                                throw new RuntimeException("未知的作者关联关系");
                            }
                        });
                    }
                    JSONObject nameAlterObject = ((JSONObject) t1).getJSONObject("name-alternatives");
                    if (Objects.nonNull(nameAlterObject)) {
                        JSONArray nameArray = nameAlterObject.getJSONArray("name");
                        authorObject.put("nameType", "作者");
                        authorObject.put("name", nameArray.getJSONObject(0).getString("surname") + nameArray.getJSONObject(0).getString("given-names"));
                        if (nameArray.size() > 1) {
                            authorObject.put("engName", nameArray.getJSONObject(1).getString("surname") + nameArray.getJSONObject(1).getString("given-names"));
                        }
                        resultArray.add(authorObject);
                    } else {
                        nameAlterObject = ((JSONObject) t1).getJSONObject("collab-alternatives");
                        if (Objects.nonNull(nameAlterObject)) {
                            JSONArray nameArray = nameAlterObject.getJSONArray("collab");
                            authorObject.put("nameType", "作者");
                            authorObject.put("name", nameArray.getString(0));
                            if (nameArray.size() > 1) {
                                authorObject.put("engName", nameArray.getJSONObject(1).getString("content"));
                            }
                            resultArray.add(authorObject);
                        }
                    }
                } else if ("editor".equals(((JSONObject) t1).getString("contrib-type"))) {
                    authorObject.put("nameType", "编者");
                    if (StringUtils.isNotBlank(((JSONObject) t1).getString("string-name"))) {
                        authorObject.put("name", ((JSONObject) t1).getString("string-name"));
                    } else {
                        authorObject.put("name", ((JSONObject) t1).getJSONObject("name-alternatives").getString("string-name"));
                        authorObject.put("engName", ((JSONObject) t1).getJSONObject("name-alternatives").getJSONObject("name").getString("surname") +
                                ((JSONObject) t1).getJSONObject("name-alternatives").getJSONObject("name").getString("given-names"));
                    }
                    resultArray.add(authorObject);
                }
            });
        });
        // 通信作者
        /*JSONArray authorNotesArray = jsonObject.getJSONArray("author-notes");
        authorNotesArray.forEach(t -> {
            JSONObject correspObject = new JSONObject();
            correspObject.put("nameType", "通信作者");
            ((JSONObject) t).getJSONArray("corresp").forEach(t1 -> {
                if (StringUtils.equals("en", ((JSONObject) t1).getString("xml:lang"))) {
                    correspObject.put("engName", ((JSONObject) t1).getJSONObject("named-content").getString("content"));
                } else {
                    correspObject.put("name", ((JSONObject) t1).getJSONObject("named-content").getString("content"));
                }
            });
            resultArray.add(correspObject);
        });*/
        return resultArray;
    }

    @ApiOperation(value = "deleteById", notes = "期刊草稿库删除接口")
    @GetMapping("deleteById")
    public void deleteById(String id) {
        journalService.deleteById(id);
    }

    @ApiOperation(value = "officialToDraft", notes = "期刊正式库取消发布接口")
    @PostMapping("officialToDraft")
    public void officialToDraft(String id) {
        journalService.revokePublish(id);
    }
}
